package org.hilo.boot.core;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Properties;

import org.hilo.boot.core.support.JacksonCustomObjectMapper;
import org.jretty.util.AlgorithmUtils;
import org.jretty.util.CollectionUtils;
import org.jretty.util.DateFormatUtils;
import org.jretty.util.ExceptionUtils;
import org.jretty.util.FileUtils;
import org.jretty.util.IOUtils;
import org.jretty.util.IpUtils;
import org.jretty.util.NestedRuntimeException;
import org.jretty.util.ObjectUtils;
import org.jretty.util.PathUtils;
import org.jretty.util.RandomUtils;
import org.jretty.util.ReflectionUtils;
import org.jretty.util.StringSplitUtils;
import org.jretty.util.StringUtils;
import org.jretty.util.ThreadUtils;
import org.jretty.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;

/**
 * 工具类统一入口。（目的： 
 *    1.方便使用、无需记忆 只需输入“UT.”工具类就列出来了； 
 *    2.统一工具类、统一管理）
 * 
 * @author zollty
 * @since 2017-4-23
 */
public class UT {
    private static final Logger logger = LoggerFactory.getLogger("");
    /*
工具类列表：
    Util.Str     -- 字符串
    Util.Coll    -- 集合
    Util.Json    -- Json处理
    Util.Date    -- 日期、格式化
    Util.Split   -- 字符串拆分
    Util.IO      -- IO流
    Util.Thread  -- 线程
    Util.Random  -- 随机数
    Util.Res     -- 资源文件
    Util.Web     -- Web相关
    Util.Algr    -- 算法
    Util.Ref     -- 反射
    Util.Excp    -- 异常
     */
    
    /** 通用Logger */
    public static Logger getLogger() {
        return logger;
    }
    
    /** 
     * 统一使用这个标准的工具类，参见 {@link #JacksonCustomObjectMapper}，
     * 如无特殊需要，请勿使用GSON、FastJSON、Jackson等其他工具类，以便于保持一致的json风格 */
    public static class Json {
        private static JacksonCustomObjectMapper objectMapper = new JacksonCustomObjectMapper(true);
        private static JacksonCustomObjectMapper objectMapperNoTransform = new JacksonCustomObjectMapper(false);
        /** 
         * 对象转换成JSON字符串，默认Long、Double等类型会转换成字符串类型，这是推荐的做法。
         */
        public static String toJSONString(Object object) {
            try {
                return objectMapper.writeValueAsString(object);
            } catch (JsonProcessingException e) {
                throw new IllegalArgumentException(e);
            }
        }
        /**
         * 同toJSONString，只是Long、Double等类型不会转换成字符串。
         */
        public static String toJSONStringNoTransform(Object object) {
            try {
                return objectMapperNoTransform.writeValueAsString(object);
            } catch (JsonProcessingException e) {
                throw new IllegalArgumentException(e);
            }
        }
        /** 
         * JSON字符串转换成对象，支持前面两个方法的逆转换
         */
        public static <T> T parseObject(String json, Class<T> clazz) {
            try {
                return objectMapper.readValue(json, clazz);
            } catch (IOException e) {
                throw new IllegalArgumentException(e);
            }
        }
        /** 
         * JSON字符串转换成泛型对象，支持前面两个方法的逆转换
         * @see com.fasterxml.jackson.databind.type.TypeFactory#constructParametricType(Class, Class...)
         */
        public static <T> T parseObject(String json, JavaType type) {
            try {
                return objectMapper.readValue(json, type);
            } catch (IOException e) {
                throw new IllegalArgumentException(e);
            }
        }
        
        /**
         * 转换成JsonNode对象
         */
        public static JsonNode readTree(String json) {
            try {
                return objectMapper.readTree(json);
            } catch (IOException e) {
                throw new IllegalArgumentException(e);
            }
        }
        
        public static JacksonCustomObjectMapper getObjectMapper() {
            return objectMapper;
        }
        public static JacksonCustomObjectMapper getObjectMapperNoTransform() {
            return objectMapperNoTransform;
        }
    }
    
    public static class Coll extends CollectionUtils {
        
    }
    
    public static class Path extends PathUtils {
        
    }
    
    public static class Str extends StringUtils {
        
    }
    
    public static class Split extends StringSplitUtils {
        
    }
    
    public static class Random extends RandomUtils {

    }

    public static class Thread extends ThreadUtils {

    }
    
    public static class IO extends IOUtils {

    }
    
    public static class File extends FileUtils {
        /**
         * 解析文本内容
         */
        public static String getFileContent(String fileFullPath) {
            return getFileContent(new java.io.File(fileFullPath), null);
        }
        
        /**
         * 解析文本内容
         */
        public static String getFileContent(java.io.File file, String charSet) {
            try {
                return getTextContent(new FileInputStream(file), charSet);
            } catch (FileNotFoundException e) {
                throw new NestedRuntimeException(e);
            }
        }
    }
    
    /*public static class Res extends ResourceUtils {
        
    }*/

    public static class Algr extends AlgorithmUtils {
        
    }
    
    public static class Date extends DateFormatUtils {
        public Date(final String datePattern) {
            super(datePattern);
        }
    }
    
    public static class Ref extends ReflectionUtils {
        
    }
    
    public static class Excp extends ExceptionUtils {
        
    }
    
    public static class Obj extends ObjectUtils {
        
    }
    
    public static class Web extends WebUtils {
        
    }
    
    public static class IP extends IpUtils {
        
    }

    
    /** 快速new一个HashMap */
    public static <K, V> FMap<K, V> newMap(K key, V value) {
        FMap<K, V> map = new FMap<>();
        map.put(key, value);
        return map;
    }
    /** 快速new一个Properties */
    public static FProp newProp(String key, Object value) {
        FProp map = new FProp();
        map.put(key, value);
        return map;
    }
    
    public static class FMap<K, V> extends HashMap<K, V>{
        private static final long serialVersionUID = 1L;
        public FMap<K, V> add(K key, V value) {
            super.put(key, value);
            return this;
        }
    }
    public static class FProp extends Properties {
        private static final long serialVersionUID = 1L;
        public FProp add(String key, Object value) {
            super.put(key, value);
            return this;
        }
    }
}
